home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / procssng / ccs / ccs-11tl.lha / lbl / hips / sources / isobuild / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-11  |  21.1 KB  |  714 lines

  1.  
  2. /* main.c  */
  3.  
  4. /* This program implements the Marching Cubes surface tiler described by
  5.  * Lorensen & Cline in the Siggraph 87 Conference Proceedings, as well as
  6.  * a version of their Dividing Cubes Algorithm.
  7.  *
  8.  * by Brian Tierney, LBL  12/90
  9.  *            Lawrence Berkeley Laboratory
  10.  *            Imaging Technologies Group
  11.  *            email: bltierney@lbl.gov
  12.  *
  13.  *    see usage routine below for command line options
  14.  *
  15.  * Parts of this code from a program written by Mike Krogh, NCSA, Feb.  2, 1990
  16.  * Portions developed at the National Center for Supercomputing Applications at
  17.  * the University of Illinois at Urbana-Champaign.
  18.  *
  19.  */
  20. /*   This program is copyright (C) 1991, Regents  of  the
  21. University  of  California.   Anyone may reproduce this software,
  22. in whole or in part, provided that:
  23. (1)  Any copy  or  redistribution  must  show  the
  24.      Regents  of  the  University of California, through its
  25.      Lawrence Berkeley Laboratory, as the source,  and  must
  26.      include this notice;
  27. (2)  Any use of this software must reference this  distribu-
  28.      tion,  state that the software copyright is held by the
  29.      Regents of the University of California, and  that  the
  30.      software is used by their permission.
  31.  
  32.      It is acknowledged that the U.S. Government has  rights
  33. to this software under  Contract DE-AC03-765F00098 between the U.S.
  34. Department of Energy and the University of California.
  35.  
  36.      This software is provided as a professional  academic  contribu-
  37. tion  for  joint exchange.  Thus it is experimental, is pro-
  38. vided ``as is'', with no warranties of any kind  whatsoever,
  39. no  support,  promise  of updates, or printed documentation.
  40. Bug reports or fixes may be sent to the author, who may or may
  41. not act on them as he desires.
  42. */
  43. #define MAIN
  44.  
  45. /* $Id: main.c,v 1.4 1992/01/31 02:05:45 tierney Exp $ */
  46.  
  47. /* $Log: main.c,v $
  48.  * Revision 1.4  1992/01/31  02:05:45  tierney
  49.  * y
  50.  *
  51.  * Revision 1.3  1992/01/30  20:05:03  davidr
  52.  * prior to Brian's changes
  53.  *
  54.  * Revision 1.2  1991/12/19  01:42:20  davidr
  55.  * added RCS identification markers
  56.  * */
  57.  
  58. static char rcsid[] = "$Id: main.c,v 1.4 1992/01/31 02:05:45 tierney Exp $";
  59.  
  60. #include "isobuild.h"        /* define MAIN must come before this!! */
  61.  
  62. char      GEOM_TYPE[32];    /* used in program status messages */
  63.  
  64. /*****************************************************/
  65. void
  66. main(argc, argv)
  67.     int       argc;
  68.     char     *argv[];
  69. {
  70.     struct header hd;        /* HIPS file header */
  71.     FILE     *fp1;
  72.     int       parse_options();    /* parse the command line options */
  73.     Data_type ***alloc_3d_data_array();
  74.     NORMAL_VECT ***alloc_3d_normal_array();
  75.     FLOAT_VECT **alloc_2d_vector_array();
  76.     Grid_type ***alloc_3d_grid_array();
  77.     CUBE_TRIANGLES **alloc_2d_cube_array();
  78.     void      tessellate_volume(), tessellate_blocks(), compute_normal_array();
  79.     void      get_max_min();
  80. #ifdef SPEED
  81.     struct timeb start_time, end_time;
  82.     float     elapsed_time;
  83. #endif
  84.  
  85.     Progname = strsave(*argv);
  86.     strcpy(MY_NAME, argv[0]);
  87.  
  88.     if (parse_options(argc, argv) == -1)
  89.     Error("error from parse_options");
  90.  
  91.     if (DIVIDING)        /* used in program status messages */
  92.     strcpy(GEOM_TYPE, "points");
  93.     else
  94.     strcpy(GEOM_TYPE, "triangles");
  95.  
  96.     if (SERVER) {
  97.     if (IN_MASK_FNAME != NULL && !DIVIDING) {
  98.         if ((in_mask_fp = fopen(IN_MASK_FNAME, "r")) == NULL)
  99.         Error("Error opening mask file");
  100.     }
  101.     surfserv();
  102.     } else {
  103.  
  104.     if (IN_FNAME != NULL) {    /* open input file */
  105.         if ((fp1 = fopen(IN_FNAME, "r")) == NULL)
  106.         Error("Input data file not found");
  107.     } else
  108.         fp1 = stdin;
  109.  
  110.     if (OUT_FNAME != NULL) {/* open output file */
  111.         if ((poly_fp = fopen(OUT_FNAME, "w")) == NULL)
  112.         Error("opening outfile file");
  113.     } else
  114.         poly_fp = stdout;
  115.  
  116.     if (get_size(fp1) < 0)    /* get size of input data (sets globals xdim,
  117.                  * ydim, zdim  */
  118.         exit_handler();
  119.  
  120.     if (IN_MASK_FNAME != NULL && !DIVIDING) {
  121.         if ((in_mask_fp = fopen(IN_MASK_FNAME, "r")) == NULL)
  122.         Error("Error opening mask file");
  123.     }
  124.     if (OUT_MASK_FNAME != NULL) {
  125.         if ((out_mask_fp = fopen(OUT_MASK_FNAME, "w")) == NULL)
  126.         Error("Error opening mask file");
  127.         init_header(&hd, MY_NAME, "", zdim, "", ydim, xdim, PFBYTE, 1, "");
  128.         update_header(&hd, argc, argv);
  129.         fwrite_header(out_mask_fp, &hd, OUT_MASK_FNAME);
  130.     }
  131.     if (data == NULL)
  132.         data = alloc_3d_data_array(zdim, ydim, xdim);    /* alloc data array */
  133.  
  134.     if (PRE_NORMALS) {    /* pre-computing normals saves time later,
  135.                  * but take LOTS of memory */
  136.         if (normals == NULL)
  137.         normals = alloc_3d_normal_array(zdim, ydim, xdim);
  138.     }
  139.     if (DUP_CHECK && prevslice == NULL) {    /* for checking for dup verts */
  140.         prevslice = alloc_2d_cube_array(ydim, xdim);
  141.         currslice = alloc_2d_cube_array(ydim, xdim);
  142.     }
  143.     /* a separate grid array is used for segmenting the data */
  144.     if (grid == NULL) {
  145.         grid = alloc_3d_grid_array(zdim, ydim, xdim);
  146.     }
  147.     if (DIVIDING && DO_CUBE_CENTER_NORMALS) {
  148.         gradient_curr_slice = alloc_2d_vector_array(ydim, xdim);
  149.         gradient_next_slice = alloc_2d_vector_array(ydim, xdim);
  150.     }
  151.     /* read in entire data set */
  152.     if (read_hips_data(fp1, data, xdim * ydim * zdim) < 0)
  153.         exit_handler();
  154.  
  155.     if (IN_MASK_FNAME != NULL && !DIVIDING) {
  156.         /* read in mask data */
  157.         if (read_mask_file(xdim * ydim * zdim) < 0)
  158.         exit_handler();
  159.     }
  160.     if (SKIP_BLOCKS)
  161.         num_blocks = block_setup();
  162.     else {
  163.         get_max_min(xdim * ydim * zdim, &data_max, &data_min);
  164.         if (VERBOSE)
  165.         fprintf(stderr, "Minimum data value: %.1f, Maximum data value: %.1f \n",
  166.             (float) data_min, (float) data_max);
  167.     }
  168.  
  169.     if (PRE_NORMALS)    /* compute normals for entire data set */
  170.         compute_normal_array();
  171.  
  172. #ifdef SPEED
  173.     ftime(&start_time);
  174. #endif
  175.     if (SKIP_BLOCKS)
  176.         tessellate_blocks();
  177.     else
  178.         tessellate_volume();
  179.  
  180. #ifdef SPEED
  181.     ftime(&end_time);
  182.     elapsed_time = ((((double) end_time.time * 1000.) +
  183.              (double) end_time.millitm) -
  184.             (((double) start_time.time * 1000.) +
  185.              (double) start_time.millitm)) / 1000.;
  186.     fprintf(stderr, "\nTime for tessellation: %f seconds\n", elapsed_time);
  187. #endif
  188.  
  189. /* #define SHOW_MEM_SIZE */
  190. #ifdef SHOW_MEM_SIZE
  191.     get_mem_size();
  192. #endif
  193.  
  194.     fclose(fp1);
  195.     fclose(poly_fp);
  196.     if (OUT_MASK_FNAME != NULL)
  197.         fclose(out_mask_fp);
  198.     if (IN_MASK_FNAME != NULL)
  199.         fclose(in_mask_fp);
  200.  
  201.     Status("Done.");
  202.     exit(0);
  203.     }
  204. }
  205.  
  206. /***************************************************************/
  207. void
  208. tessellate_volume()
  209. {                /* tessellate entire volume */
  210.     int       npoints = 0;
  211.     int       num_slices;
  212.     int      *num_voxels;
  213.     register int slice;
  214.  
  215.     if (TVAL < data_min || TVAL > data_max) {
  216.     fprintf(stderr, "Error: threshold value %.1f is not between %.2f and %.2f \n",
  217.         (float) TVAL, (float) data_min, (float) data_max);
  218.     return;
  219.     }
  220.     if (SX > 0 || SY > 0 || SZ > 0 || EX < xdim || EY < ydim || EZ < zdim) {
  221.     SMALLER_BOX = 1;    /* global flag indication using reduced
  222.                  * volume */
  223.     fprintf(stderr, "Using partial input data set: from %d,%d,%d to %d,%d,%d\n",
  224.         SX, SY, SZ, EX, EY, EZ);
  225.     }
  226.     if (EX > xdim)        /* set-up for handling partial volumes */
  227.     EX = xdim;
  228.     if (EY > ydim)
  229.     EY = ydim;
  230.     if (EZ > zdim)
  231.     EZ = zdim;
  232.  
  233.     num_voxels = Calloc(zdim, int);
  234.  
  235.     if (DUP_CHECK)
  236.     init_dup_vertex_check_arrays();
  237.     if (DIVIDING && DO_CUBE_CENTER_NORMALS) {
  238.     memset(gradient_curr_slice[0], 0, sizeof(FLOAT_VECT) * xdim * ydim);
  239.     memset(gradient_next_slice[0], 0, sizeof(FLOAT_VECT) * xdim * ydim);
  240.     }
  241.     if (SEG_METHOD == 4) {
  242.     fprintf(stderr, "\nisobuild: Using mask file for segmentation (at isoval %.2f) ...\n", (float) TVAL);
  243.     } else if (SEG_METHOD == 0) {
  244.     fprintf(stderr, "\nisobuild: Segmenting data at isoval %.2f ...\n",
  245.         (float) TVAL);
  246.     for (slice = SZ; slice < EZ; slice++) {
  247.         num_voxels[slice] = seg_slice_thresh(TVAL, data[slice],
  248.                          grid[slice], SX, SY,
  249.                          EX, EY, slice);
  250.         if (SMOOTH_GRID)
  251.         smooth_slice(slice);
  252.     }
  253.     } else {
  254.     fprintf(stderr, "\nisobuild: Performing flood fill segmentation at isoval %.2f ...\n",
  255.         (float) TVAL);
  256.     flood_fill_segmentation(TVAL, BRIDGE_TYPE);
  257.     }
  258.  
  259.     Status("Tessellating data...");
  260.  
  261.     num_slices = EZ - 1;    /* dont want to do last slice */
  262.     for (slice = SZ; slice < num_slices; slice++) {
  263.     if (VERBOSE2)
  264.         fprintf(stderr, "tessellating slice: %d \n", slice);
  265.     if (slice % 10 == 0) {
  266.         fprintf(stderr, "Tessellating slice %d,  %d %s so far \n",
  267.             slice, npoints, GEOM_TYPE);
  268.     }
  269.     if (SEG_METHOD > 0 || num_voxels[slice] > 0) {
  270.         if (!DIVIDING)
  271.         npoints += iso_march(SX, SY, EX, EY, slice);
  272.         else
  273.         npoints += iso_divide(SX, SY, EX, EY, slice);
  274.     }
  275.     }
  276.  
  277.     if (out_mask_fp != NULL)
  278.     write_mask_slices(zdim);
  279.  
  280.     if (!DIVIDING) {
  281.     dump_polys(0);        /* make sure all vertices have been written */
  282.     } else {
  283.     dump_points(0);
  284.     }
  285.     fprintf(stderr, "\n%s: %d %s generated\n\n", MY_NAME, npoints, GEOM_TYPE);
  286.  
  287.  
  288.     return;
  289. }
  290.  
  291. /***************************************************************/
  292. void
  293. tessellate_blocks()
  294. {                /* tessellate block by block */
  295.     int       npoints = 0, prev_xloc;
  296.     int       num_slices, skip_cnt = 0;
  297.     BLOCK_INFO *binfo_ptr, *binfo_ptr2;
  298.     register int i, slice, block, xloc, yloc;
  299.  
  300.     if (TVAL < data_min || TVAL > data_max) {
  301.     fprintf(stderr, "Error: threshold value %.1f is not between %.2f and %.2f \n",
  302.         (float) TVAL, (float) data_min, (float) data_max);
  303.     return;
  304.     }
  305.     if (SX > 0 || SY > 0 || SZ > 0 || EX < xdim || EY < ydim || EZ < zdim) {
  306.     fprintf(stderr, "Using partial input data set: from %d,%d,%d to %d,%d,%d\n",
  307.         SX, SY, SZ, EX, EY, EZ);
  308.     }
  309.     if (EX > xdim)        /* set-up for handling partial volumes */
  310.     EX = xdim;
  311.     if (EY > ydim)
  312.     EY = ydim;
  313.     if (EZ > zdim)
  314.     EZ = zdim;
  315.  
  316.     if (DUP_CHECK)
  317.     init_dup_vertex_check_arrays();
  318.     if (DIVIDING && DO_CUBE_CENTER_NORMALS) {
  319.     memset(gradient_curr_slice[0], 0, sizeof(FLOAT_VECT) * xdim * ydim);
  320.     memset(gradient_next_slice[0], 0, sizeof(FLOAT_VECT) * xdim * ydim);
  321.     }
  322.     if (SEG_METHOD == 1) {
  323.     SEG_METHOD = 0;
  324.     Status("Flood fill segmentation not allow with skip slocks option!");
  325.     }
  326.     fprintf(stderr, "\nisobuild: Segmenting data at isoval %.2f ...\n",
  327.         (float) TVAL);
  328.     for (slice = SZ; slice < EZ; slice++) {
  329.     /* initialize grid to 0 */
  330.     memset((char *) grid[slice][0], 0, xdim * ydim * sizeof(Grid_type));
  331.     for (block = 0; block < num_blocks; block++) {
  332.         binfo_ptr = &block_info_array[slice][block];
  333.         yloc = binfo_ptr->yloc;
  334.         xloc = binfo_ptr->xloc;
  335.         if (xloc > 0)
  336.         prev_xloc = xloc - binfo_ptr->width;
  337.         else
  338.         prev_xloc = 0;
  339.         if (prev_xloc >= SX && yloc >= SY &&
  340.         prev_xloc <= EX && yloc <= EY) {
  341.  
  342.         if (binfo_ptr->max < TVAL)
  343.              /* do nothing, slice already set to 0 */ ;
  344.         else if (binfo_ptr->min > TVAL) {
  345.  
  346.             /* set grid block to 1 */
  347.             for (i = 0; i < binfo_ptr->height; i++) {
  348.             memset((char *) &binfo_ptr->grid[yloc++][xloc], 1,
  349.                    (binfo_ptr->width) * sizeof(Grid_type));
  350.             }
  351.         } else
  352.             threshold_block(binfo_ptr, TVAL);
  353.         }            /* if check bounds */
  354.     }
  355.     }
  356.     if (SMOOTH_GRID) {
  357.     for (slice = SZ; slice < EZ; slice++)
  358.         smooth_slice(slice);
  359.     }
  360.     skip_cnt = 0;
  361.     num_slices = EZ - 1;    /* dont want to do last slice */
  362.  
  363.     Status("Tessellating data...");
  364.  
  365.     for (slice = SZ; slice < num_slices; slice++) {
  366.     if (slice % 10 == 0) {
  367.         fprintf(stderr, "Tessellating slice %d,  %d %s so far \n",
  368.             slice, npoints, GEOM_TYPE);
  369.     }
  370.     for (block = 0; block < num_blocks; block++) {
  371.         binfo_ptr = &block_info_array[slice][block];
  372.         binfo_ptr2 = &block_info_array[slice + 1][block];
  373.  
  374.         yloc = binfo_ptr->yloc;
  375.         xloc = binfo_ptr->xloc;
  376.         if (xloc > 0)
  377.         prev_xloc = xloc - binfo_ptr->width;
  378.         else
  379.         prev_xloc = 0;
  380.         if (prev_xloc >= SX && yloc >= SY &&
  381.         prev_xloc <= EX && yloc <= EY) {
  382.         if (((binfo_ptr->max < TVAL) &&
  383.              (binfo_ptr2->max < TVAL)) ||
  384.             ((binfo_ptr->min > TVAL) &&
  385.              (binfo_ptr2->min > TVAL)))
  386.             skip_cnt++;
  387.         else {
  388.             if (!DIVIDING)
  389.             npoints += iso_march_block(binfo_ptr->xloc,
  390.                            binfo_ptr->yloc, slice,
  391.                            binfo_ptr->width,
  392.                            binfo_ptr->height,
  393.                            SX, SY, EX - 1, EY - 1);
  394.             else
  395.             npoints += iso_divide_block(binfo_ptr->xloc,
  396.                             binfo_ptr->yloc, slice,
  397.                             binfo_ptr->width,
  398.                             binfo_ptr->height,
  399.                             binfo_ptr->grid,
  400.                             binfo_ptr2->grid,
  401.                             SX, SY, EX - 1, EY - 1);
  402.         }
  403.         }
  404.     }
  405.     }
  406.     if (VERBOSE)
  407.     fprintf(stderr, "Skipped %d blocks out of %d \n", skip_cnt,
  408.         num_blocks * num_slices);
  409.  
  410.  
  411.     if (!DIVIDING)
  412.     dump_polys(0);        /* make sure all vertices have been written */
  413.     else
  414.     dump_points(0);
  415.     fprintf(stderr, "\n%s: %d %s generated\n", MY_NAME, npoints, GEOM_TYPE);
  416.  
  417.     return;
  418. }
  419.  
  420. /****************************************************************/
  421.  /*
  422.   * this routine can be used to check the results of the segmentation by
  423.   * creating a file containing the segmentation mask
  424.   */
  425. write_mask_slices(num_slices)
  426.     int       num_slices;
  427. {
  428.  
  429.     register int i, j, k;
  430.  
  431.     if (VERBOSE)
  432.     Status("Writing mask file...");
  433.  
  434.     for (i = 0; i < num_slices; i++) {
  435.     for (j = 0; j < ydim; j++)
  436.         for (k = 0; k < xdim; k++)
  437.         if (grid[i][j][k] > 0)
  438.             grid[i][j][k] = 255;
  439.         else
  440.             grid[i][j][k] = 0;
  441.  
  442.     if ((Fwrite(grid[i][0], sizeof(Grid_type), xdim * ydim,
  443.             out_mask_fp)) != xdim * ydim)
  444.         perror("error writing mask image");
  445.     }
  446. }
  447.  
  448. /**************************** parse_options ****************************/
  449. int
  450. parse_options(argc, argv)
  451.     int       argc;
  452.     char     *argv[];
  453. {
  454.     /* see isovis.h for default values */
  455.  
  456.     void      usage();
  457.     int       val;
  458.  
  459.     /* Interpret options  */
  460.     while (--argc > 0 && (*++argv)[0] == '-') {
  461.     char     *s;
  462.     for (s = argv[0] + 1; *s; s++)
  463.         switch (*s) {
  464.         case 'b':
  465.         if (argc < 2)
  466.             usage();
  467.         sscanf(*++argv, "%d", &BRIDGE_TYPE);
  468.         argc--;
  469.         break;
  470.         case 'd':
  471.         DUP_CHECK = abs(DUP_CHECK - 1);
  472.         break;
  473.         case 'D':
  474.         SERVER = abs(SERVER - 1);
  475.         break;
  476.         case 'E':
  477.         if (argc < 4)
  478.             usage();
  479.         sscanf(*++argv, "%d", &EX);
  480.         sscanf(*++argv, "%d", &EY);
  481.         sscanf(*++argv, "%d", &EZ);
  482.         argc -= 3;
  483.         break;
  484.         case 'f':
  485.         SKIP_BLOCKS = abs(SKIP_BLOCKS - 1);
  486.         break;
  487.         case 'F':
  488.         SMOOTH_GRID = abs(SMOOTH_GRID - 1);
  489.         break;
  490.         case 'g':
  491.         MARCH_NORMALS = abs(MARCH_NORMALS - 1);
  492.         break;
  493.         case 'h':
  494.         usage();
  495.         break;
  496.         case 'i':
  497.         if (argc < 2)
  498.             usage();
  499.         IN_FNAME = *++argv;
  500.         fprintf(stderr, " using input data file: %s\n", IN_FNAME);
  501.         argc--;
  502.         break;
  503.         case 'm':
  504.         if (argc < 2)
  505.             usage();
  506.         IN_MASK_FNAME = *++argv;
  507.         fprintf(stderr, " input segmentation mask file: %s\n",
  508.             IN_MASK_FNAME);
  509.         argc--;
  510.         break;
  511.         case 'M':
  512.         if (argc < 2)
  513.             usage();
  514.         OUT_MASK_FNAME = *++argv;
  515.         fprintf(stderr, " writing segmentation mask to file: %s\n",
  516.             OUT_MASK_FNAME);
  517.         argc--;
  518.         break;
  519.         case 'n':
  520.         PRE_NORMALS = abs(PRE_NORMALS - 1);
  521.         break;
  522.         case 'N':
  523.         DO_CUBE_CENTER_NORMALS = abs(DO_CUBE_CENTER_NORMALS - 1);
  524.         break;
  525.         case 'o':
  526.         if (argc < 2)
  527.             usage();
  528.         OUT_FNAME = *++argv;
  529.         fprintf(stderr, " using output data file: %s\n", OUT_FNAME);
  530.         argc--;
  531.         break;
  532.         case 'O':
  533.         if (argc < 2)
  534.             usage();
  535.         sscanf(*++argv, "%d", &OUTPUT_TYPE);
  536.         argc--;
  537.         break;
  538.         case 'p':
  539.         DIVIDING = abs(DIVIDING - 1);
  540.         break;
  541.         case 'P':
  542.         if (argc < 2)
  543.             usage();
  544.         sscanf(*++argv, "%d", &PORT_NUM);
  545.         argc--;
  546.         break;
  547.         case 's':
  548.         if (argc < 2)
  549.             usage();
  550.         sscanf(*++argv, "%d", &SEG_METHOD);
  551.         argc--;
  552.         break;
  553.         case 'S':
  554.         if (argc < 4)
  555.             usage();
  556.         sscanf(*++argv, "%d", &SX);
  557.         sscanf(*++argv, "%d", &SY);
  558.         sscanf(*++argv, "%d", &SZ);
  559.         argc -= 3;
  560.         break;
  561.         case 't':
  562.         if (argc < 2)
  563.             usage();
  564.         sscanf(*++argv, "%d", &val);
  565.         TVAL = (Data_type) val;
  566.         argc--;
  567.         break;
  568.         case 'u':
  569.         usage();
  570.         break;
  571.         case 'v':
  572.         VERBOSE = abs(VERBOSE - 1);
  573.         break;
  574.         case 'V':
  575.         VERBOSE2 = abs(VERBOSE2 - 1);
  576.         if (VERBOSE2)
  577.             VERBOSE = 1;
  578.         break;
  579.         default:
  580.         usage();
  581.         break;
  582.         }
  583.     }                /* while */
  584.  
  585.     if (IN_FNAME == NULL && OUT_FNAME == NULL)
  586.     SERVER = 1;
  587.  
  588.     if (!SERVER && (IN_FNAME == NULL || OUT_FNAME == NULL)) {
  589.     fprintf(stderr, "\n ERROR: Input and Output file names must be specified. \n");
  590.     usage();
  591.     }
  592.     if (PRE_NORMALS && !DIVIDING) {
  593.     fprintf(stderr, "Pre-computing normals not allowed with marching cubes. \n");
  594.     PRE_NORMALS = 0;    /* this option for dividing cubes only */
  595.     }
  596.     if (OUTPUT_TYPE > 4) {
  597.     fprintf(stderr, "\n ERROR: Invalid output type. \n");
  598.     usage();
  599.     }
  600.     if (OUTPUT_TYPE == 2) {
  601.     fprintf(stderr, "Output file will be movie.BYU format. \n");
  602.     DUP_CHECK = 1;        /* must produce edge list for movie.byu files */
  603.     DIVIDING = 0;        /* must use marching cubes method */
  604.     SERVER = 0;        /* movie.byu server not supported */
  605.     MARCH_NORMALS = 0;    /* movie.byu doesn't handle normals */
  606.     SMALL_CHUNKS = 0;    /* chunks not allowed in move.byu */
  607.     }
  608.     if (OUTPUT_TYPE == 3) {
  609.     fprintf(stderr, "Output file will be wavefront format. \n");
  610.     DUP_CHECK = 1;        /* must produce edge list for wavefront files */
  611.     DIVIDING = 0;        /* must use marching cubes method */
  612.     SERVER = 0;        /* wavefront server not supported */
  613.     SMALL_CHUNKS = 0;    /* chunks not implemented in wavefront */
  614.     }
  615.     if (OUTPUT_TYPE == 4) {
  616.     fprintf(stderr, "Output file will be sunvision.vff format. \n");
  617.     DUP_CHECK = 1;
  618.     DIVIDING = 0;
  619.     SERVER = 0;
  620.     SMALL_CHUNKS = 0;    /* chunks not allowed in sunvision.vff */
  621.     }
  622.     if (SEG_METHOD > 0 && SKIP_BLOCKS) {
  623.     /* ERROR: Can't use skip-block option with flood fill segmentation */
  624.     SKIP_BLOCKS = 0;
  625.     }
  626.     if (SEG_METHOD > 2) {
  627.     fprintf(stderr, "\n ERROR: Invalid segmentation method. \n");
  628.     usage();
  629.     }
  630.     if (IN_MASK_FNAME != NULL && !DIVIDING) {
  631.     /* ERROR: Can't use skip-block option with input mask (no advantage) */
  632.     SKIP_BLOCKS = 0;
  633.     SMOOTH_GRID = 0;    /* not implemented with mask input */
  634.     SEG_METHOD = 4;        /* no segmentation at all, just use mask */
  635.     }
  636.     if (!DIVIDING && IN_MASK_FNAME != NULL) {
  637.     fprintf(stderr, "\n ERROR: Mask segmentation allowed with dividing cubes only. \n");
  638.     SEG_METHOD = 0;
  639.     }
  640.     if (SEG_METHOD == 1) {
  641.     fprintf(stderr, "Using flood fill segmentation method. \n");
  642.     }
  643.     if (!DIVIDING && DUP_CHECK)
  644.     fprintf(stderr, "Checking for duplicate vertices. \n");
  645.  
  646.     if (!DIVIDING)
  647.     fprintf(stderr, "Output will be triangle vertices. \n");
  648.     else
  649.     fprintf(stderr, "Output will be points with normals. \n");
  650.  
  651.     if (SX < 0 || SY < 0 || SZ < 0 || EX < SX || EY < SY || EY < SZ) {
  652.     fprintf(stderr, "\n ERROR: Invalid starting or ending grid locations.\n");
  653.     usage();
  654.     }
  655.     return 0;
  656. }
  657.  
  658. /**************************** usage ****************************/
  659.  
  660. void
  661. usage()
  662. {
  663.     fprintf(stderr, "\nusage: %s [-i 3d_data.hips][-o outfile][-O N][-t NN][-p][-s N][-N][-v] \n", MY_NAME);
  664.  
  665.     fprintf(stderr, "  -i file   HIPS file name (default = stdin) \n");
  666.     fprintf(stderr, "  -o file   output file name \n");
  667.     fprintf(stderr, "  -O N      output type (default = %d) \n", OUTPUT_TYPE);
  668.     fprintf(stderr, "             ( 0=LBL, 1=ASCII, 2=byu, 3=wavefront, 4=sunvision (.vff) )\n");
  669.     fprintf(stderr, "  -t NN     surface threshold value (default = %d) \n", (int) TVAL);
  670.     if (DIVIDING)
  671.     fprintf(stderr, "  -p        output points, not triangles (Dividing Cubes) (default = points) \n");
  672.     else
  673.     fprintf(stderr, "  -p        output points, not triangles (Dividing Cubes) (default = triangles) \n");
  674.     fprintf(stderr, "  -s N      segmentation method   (default = %d) \n", SEG_METHOD);
  675.     fprintf(stderr, "             ( 0 = thresholding, 1 = flood fill, 2 = flood with gradient ) \n");
  676.     fprintf(stderr, "  -D        run as a server, if no file names, this is assumed \n");
  677.     fprintf(stderr, "  -m file   HIPS file to use as a segmentation mask\n");
  678.  
  679.  
  680.     fprintf(stderr, "\n other options:\n");
  681.     fprintf(stderr, "  -v[V]     verbose mode(s) \n");
  682.     if (MARCH_NORMALS)
  683.     fprintf(stderr, "  -g        compute normals for gouraud shading. (default = yes) \n");
  684.     else
  685.     fprintf(stderr, "  -g        compute normals for gouraud shading. (default = no) \n");
  686.     if (SMOOTH_GRID)
  687.     fprintf(stderr, "  -F        smooth segmentation grid after threshold (default = yes)\n");
  688.     else
  689.     fprintf(stderr, "  -F        smooth segmentation grid after threshold (default = no)\n");
  690.     fprintf(stderr, "  -P NN     server port number (default = %d)\n", PORT_NUM);
  691.     fprintf(stderr, "  -b N      type of connectivity bridge: (default = %d) \n", BRIDGE_TYPE);
  692.     fprintf(stderr, "             ( 0 = none, 1 = 2D, 2 = 3D weak, 3 = 3D strong ) \n");
  693.     if (SKIP_BLOCKS)
  694.     fprintf(stderr, "  -f        pre-pass to compute min/max of data blocks (default = prepass)\n");
  695.     else
  696.     fprintf(stderr, "  -f        pre-pass to compute min/max of data blocks (default = no prepass)\n");
  697.     if (PRE_NORMALS)
  698.     fprintf(stderr, "  -n        pre-compute all normals (default = yes) \n");
  699.     else
  700.     fprintf(stderr, "  -n        pre-compute all normals (default = no) \n");
  701.     if (DO_CUBE_CENTER_NORMALS)
  702.     fprintf(stderr, "  -N        fast, less accurate normals for dividing cubes (default = slow)\n");
  703.     else
  704.     fprintf(stderr, "  -N        fast, less accurate normals for dividing cubes (default = fast)\n");
  705.     if (DUP_CHECK)
  706.     fprintf(stderr, "  -d        check for duplicate triangle vertices (default = check) \n");
  707.     else
  708.     fprintf(stderr, "  -d        check for duplicate triangle vertices (default = no check) \n");
  709.     fprintf(stderr, "  -M file   write segmentation mask to HIPS file\n");
  710.     fprintf(stderr, "  -S NN NN NN starting x,y,z data grid location (default = 0,0,0)\n");
  711.     fprintf(stderr, "  -E NN NN NN ending x,y,z data grid location (default = xmax, ymax, zmax)\n\n");
  712.     exit(-1);
  713. }
  714.